package com.mgq.java8.timeapi;

import java.time.*;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;
import static java.time.temporal.TemporalAdjusters.nextOrSame;

/**
 * <b>功能：</b>新的时间api<br>
 * <b>Copyright TCSL</b>
 * <li>版本&nbsp;&nbsp;&nbsp;&nbsp;修改日期&nbsp;&nbsp;&nbsp;&nbsp;部　　门&nbsp;&nbsp;&nbsp;&nbsp;作　者&nbsp;&nbsp;&nbsp;&nbsp;变更内容</li><hr>
 * <li>v1.0&nbsp;&nbsp;&nbsp;&nbsp;20220613&nbsp;&nbsp;营业后台&nbsp;&nbsp;&nbsp;&nbsp;马广奇&nbsp;&nbsp;&nbsp;&nbsp;创建类</li>
 * <br><br>
 *
 * @author 马广奇
 * @version 2022-06-13 11:19
 */
public class NewTimeApi {


    //
    public static void userLocalDate() {
        LocalDate date = LocalDate.of(2022, 6, 13);
        //年 2022年
        int year = date.getYear();
        //月 6月
        Month month = date.getMonth();
        //所在月的第几天  13号
        int dayOfMonth = date.getDayOfMonth();
        //周 周一
        DayOfWeek dow = date.getDayOfWeek();
        //所在月有多少天 6月共30天
        int len = date.lengthOfMonth();
        //是否是闰年 否
        boolean leap = date.isLeapYear();

        //parse()解析字符串
        LocalDate parse = LocalDate.parse("2022-06-13");
        System.out.println(parse.getYear());

        System.out.println(year);
        System.out.println(month);
        System.out.println(dayOfMonth);
        System.out.println(dow);
        System.out.println(len);
        System.out.println(leap);
    }

    public static void userTemporalField() {
        //temporal: 时间场
        LocalDate date = LocalDate.of(2022, 6, 13);
        //Chrono 计时码表
        //等价于getYear()
        int year = date.get(ChronoField.YEAR);
        //等价于getMonth()
        int month = date.get(ChronoField.MONTH_OF_YEAR);
        int day = date.get(ChronoField.DAY_OF_MONTH);

        System.out.println(year);
        System.out.println(month);
        System.out.println(day);
    }

    public static void useLocalTime() {
        //13:45:20
        LocalTime time = LocalTime.of(13, 45, 20);
        int hour = time.getHour();
        int minute = time.getMinute();
        int second = time.getSecond();

        LocalTime parse = LocalTime.parse("13:45:20");
        System.out.println(parse.getHour());
        System.out.println(hour);
        System.out.println(minute);
        System.out.println(second);
    }

    //合并日期和时间LocalDateTime
    public static void useLocalDateTime() {
        LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);
        //合并日期和时间
        LocalDate date = LocalDate.of(2022, 6, 13);
        LocalTime time = LocalTime.of(13, 45, 20);
        LocalDateTime dt2 = LocalDateTime.of(date, time);
        LocalDateTime dt3 = date.atTime(13, 45, 20);
        LocalDateTime dt4 = date.atTime(time);
        LocalDateTime dt5 = time.atDate(date);
    }

    //机器时间类Instant (立即的,瞬间)
    public static void useInstance() {
        //几个方法相同,都表示3秒后的时间
        Instant.ofEpochSecond(3);
        Instant.ofEpochSecond(3, 0);
        //第二个参数是纳秒
        Instant.ofEpochSecond(2, 1_000_000_000);
        Instant.ofEpochSecond(4, -1_000_000_000);
        Instant.now();
    }

    public static void useDurationAndPeriod() {
        //duration: Duration类主要用于以秒和纳秒衡量时间的长短，你不能仅向between方法传递一个LocalDate对象做参数。
        //duration只能用在LocalDateTime,LocalTime,Instant类
        LocalTime time1 = LocalTime.of(13, 45, 20);
        LocalTime time2 = LocalTime.of(13, 46, 20);

        LocalDateTime dateTime1 = LocalDateTime.of(2022, 6, 13, 11, 57, 20);
        LocalDateTime dateTime2 = LocalDateTime.of(2022, 6, 13, 11, 58, 20);

        Instant instant1 = Instant.ofEpochSecond(3);
        Instant instant2 = Instant.ofEpochSecond(4);

        Duration between = Duration.between(time1, time2); //相差60s
        Duration between2 = Duration.between(dateTime1, dateTime2); //相差60s
        Duration between3 = Duration.between(instant1, instant2); //相差1s


        System.out.println(between.getSeconds());
        System.out.println(between2.getSeconds());
        System.out.println(between3.getSeconds());

        //period类可以用在LocalDate
        Period tenDays = Period.between(LocalDate.of(2014, 3, 8),
                LocalDate.of(2014, 3, 18));
        Duration threeMinutes = Duration.ofMinutes(3);
        Duration threeMinutes2 = Duration.of(3, ChronoUnit.MINUTES);
        Period tenDays2 = Period.ofDays(10);
        Period threeWeeks = Period.ofWeeks(3);
        Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
        System.out.println(tenDays2.getDays());
    }

    //manipulate 操纵时间类
    public static void processLocalDate() {
        LocalDate date = LocalDate.of(2022, 6, 13);
        date = date.withYear(2021);
        date = date.withDayOfMonth(25);
        date = date.with(ChronoField.MONTH_OF_YEAR, 9);
        //2021年9月25日
        System.out.println(date);

        //以相对的方式修改
        LocalDate date1 = date.plusDays(2);
        //减去3年 2018-09-27
        LocalDate date2 = date1.minusYears(3);
        System.out.println(date2);
    }

    //使用TemporalAdjuster类
    //有的时候，你需要进行一些更加复杂的操作，比如，将日期调整到下个周日、下个工作日，或者是本月的最后一天。
    // 这时，你可以使用重载版本的with方法，向其传递一个提供了更多定制化选择的TemporalAdjuster对象，
    //更加灵活地处理日期。对于最常见的用例，日期和时间API已经提供了大量预定义的
    //TemporalAdjuster。
    //dayOfWeekInMonth 创建一个新的日期，它的值为同一个月中每一周的第几天
    //firstDayOfMonth 创建一个新的日期，它的值为当月的第一天
    //firstDayOfNextMonth 创建一个新的日期，它的值为下月的第一天
    //firstDayOfNextYear 创建一个新的日期，它的值为明年的第一天
    //firstDayOfYear 创建一个新的日期，它的值为当年的第一天
    //firstInMonth 创建一个新的日期，它的值为同一个月中，第一个符合星期几要求的值
    //lastDayOfMonth 创建一个新的日期，它的值为当月的最后一天
    //lastDayOfNextMonth 创建一个新的日期，它的值为下月的最后一天
    //lastDayOfNextYear 创建一个新的日期，它的值为明年的最后一天
    //lastDayOfYear 创建一个新的日期，它的值为今年的最后一天
    //lastInMonth 创建一个新的日期，它的值为同一个月中，最后一个符合星期几要求的值
    //next/previous
    //创建一个新的日期，并将其值设定为日期调整后或者调整前，第一个符合指定星
    //期几要求的日期
    //nextOrSame/previousOrSame
    //创建一个新的日期，并将其值设定为日期调整后或者调整前，第一个符合指定星
    //期几要求的日期，如果该日期已经符合要求，直接返回该对象
    public static void testTemporalAdjuster() {
        LocalDate date1 = LocalDate.of(2022, 6, 13);
        //下个周日是几号
        LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY));
        //这个月最后一天
        LocalDate date3 = date2.with(lastDayOfMonth());

        //使用自定义的时间调整类 TemporalAdjuster.计算下一个工作日的时间
        LocalDate nextWorkDay = date1.with(new NextWorkingDay());

        //使用lambda表达式.和上面的相同
        TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(
                temporal -> {
                    DayOfWeek dow =
                            DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
                    int dayToAdd = 1;
                    if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
                    if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
                    return temporal.plus(dayToAdd, ChronoUnit.DAYS);
                });

        LocalDate lambdaNextWorkDay = date1.with(nextWorkingDay);
        System.out.println(lambdaNextWorkDay);
        System.out.println(nextWorkDay);

        //System.out.println(date2);
        //System.out.println(date3);
    }

    public static void main(String[] args) {
//        userLocalDate();
        //userTemporalField();
        //useLocalTime();
        //useDurationAndPeriod();
        //processLocalDate();
        testTemporalAdjuster();
    }


}
